/*** server ***/
package main;

import comm.Communication;
import java.util.ArrayList;
import java.util.Arrays;
import util.Utils;

public class Main {

    private static int PORT = 4444;
    public static final int NUM_SERVERS = 5;
    private static int CURRENT_SERVER = 0;

    private static String[] servers = new String[NUM_SERVERS];
    private static int[] weights = new int[NUM_SERVERS];
    private static int[] request = new int[NUM_SERVERS];
    /* STATES
     * 0 - available    
     * 1 - read lock    
     * 2 - write lock   
     * 3 - unavailable  
     */
    private static int[] states = new int[NUM_SERVERS];
    private static String[] readingServers;
    private static String[] writingServers;
    public static int readingQuorum;
    public static int writingQuorum;

    public static int requestNum = 0;

    public static String[] getServers() {
        return servers;
    }

    public static String getServer(int ind) {
        if (ind < 0 || ind >= NUM_SERVERS) {
            return null;
        }
        return servers[ind];
    }

    public static void setServers(String[] servers) {
        Main.servers = servers;
    }

    public static void setServer(int ind, String server) {
        if (ind < 0 || ind >= NUM_SERVERS) {
            return;
        }
        Main.servers[ind] = server;
    }

    public static int getWeight(int ind) {
        return weights[ind];
    }

    public static void setWeight(int ind, int weight) {
        if (ind < 0 || ind >= NUM_SERVERS) {
            return;
        }
        weights[ind] = weight;
    }

    public static int getRequestNum() {
        requestNum++;
        return requestNum;
    }

    public static int getRequest(int ind) {
        return request[ind];
    }

    public static void setRequest(int ind, int requestNum) {
        if (ind < 0 || ind >= NUM_SERVERS) {
            return;
        }
        request[ind] = requestNum;
    }

    public static int[] getAllStates() {
        return states;
    }

    public static int getState(int ind) {
        return states[ind];
    }

    public static void setState(int ind, int state) {
        if (ind < 0 || ind >= NUM_SERVERS) {
            return;
        }
        states[ind] = state;
    }

    public static int getPort() {
        return PORT;
    }

    public static int getReadingServer() {
        for(int i=0; i<NUM_SERVERS; i++){
            int ind = (CURRENT_SERVER + i)%NUM_SERVERS;
            if(states[ind]==0){
                CURRENT_SERVER = (ind + 1)%NUM_SERVERS;
                return ind;
            }
        }
        return -1;
    }

    public static int getWritingServer() {
        for(int i=0; i<NUM_SERVERS; i++){
            int ind = (CURRENT_SERVER + i)%NUM_SERVERS;
            if(states[ind]==0){
                CURRENT_SERVER = (ind + 1)%NUM_SERVERS;
                return ind;
            }
        }
        return -1;
    }

    public static String[] getReadingServers() {
        int[] aux = weights.clone();
        ArrayList<String> serv = new ArrayList<String>();
        Arrays.sort(aux);
        int i, j, k, sum;

        for (i = NUM_SERVERS - 1, k = sum = 0; sum < readingQuorum && i >= 0; i--) {
            for (j = 0; j < NUM_SERVERS; j++) {
                if (aux[i] == weights[j]) {
                    k = j;
                    j = NUM_SERVERS; // sair do loop interno [break sairia de todos?]
                }
            }
            serv.add(servers[k]);
            sum += weights[k];
        }

        return serv.toArray(new String[]{});
    }

    public static String[] getWritingServers() {
        int[] aux = weights.clone();
        ArrayList<String> serv = new ArrayList<String>();
        Arrays.sort(aux);
        int i, j, k, sum;

        for (i = NUM_SERVERS - 1, k = sum = 0; sum < writingQuorum && i >= 0; i--) {
            for (j = 0; j < NUM_SERVERS; j++) {
                if (aux[i] == weights[j]) {
                    k = j;
                    j = NUM_SERVERS; // sair do loop interno [break sairia de todos?]
                }
            }
            serv.add(servers[k]);
            sum += weights[k];
        }

        return serv.toArray(new String[]{});
    }

    public static void main(String[] args) {

        Utils.setServerAttributes();

        /** teste **/
        writingQuorum = 12;
        readingQuorum = 6;
        readingServers = getReadingServers();
        for (int i = 0; i < readingServers.length; i++) {
            System.err.println(readingServers[i]);
        }

        writingServers = getWritingServers();
        for (int i = 0; i < writingServers.length; i++) {
            System.err.println(writingServers[i]);
        }

        new Communication().connect();
    }
}